package demo4

import "fmt"

/*
	空接口类型（interface{}）
	1. 空接口是接口类型的特殊形式，空接口没有任何方法，因此任何类型都无须实现空接口。
		从实现的角度看，任何值都满足这个接口的需求。因此空接口类型可以保存任何值，也可以从空接口中取出原值。
	2. 在泛型和模板出现前，空接口是一种非常灵活的数据抽象保存和使用的方法。
	3. 空接口的内部实现保存了对象的类型和指针。使用空接口保存一个数据的过程会比直接用数据对应类型的变量保存稍慢。
		因此在开发中，应在需要的地方使用空接口，而不是在所有地方使用空接口。
*/

// TestDemo410 空接口类型（interface{}）
func TestDemo410() {
	/* demo1: 将值保存到空接口 */
	var any interface{}

	any = 1
	fmt.Println(any)

	any = "hello"
	fmt.Println(any)

	any = false
	fmt.Println(any)

	/* demo2: 从空接口获取值 */
	// 声明变量 a, int 类型， 初始值 1
	var a = 1

	// 声明i变量, 类型为interface{}, 初始值为a, 此时i的值变为1
	var i interface{} = a

	// 声明 b 变量，尝试复制 i
	var b int

	// 不能直接赋值，需要使用类型断言
	// b = i

	b = i.(int)

	fmt.Println(a, i, b)

	/*
		demo3: 空接口的值比较
			1. 空接口在保存不同的值后，可以和其他变量值一样使用==进行比较操作。空接口的比较有以下几种特性。
				1.1 类型不同的空接口间的比较结果不相同
				1.2 不能比较空接口中的动态值
	*/
	/* demo31 */
	// 保存 int
	var c interface{} = 100

	// 保存 strign
	var d interface{} = "Hello"

	// 比较 interface{}
	fmt.Println("c d 比较", c == d)

	/* demo32 */
	// slice1
	var e interface{} = []int{10}

	// slice2
	var f interface{} = []int{20}

	// 比较报错: panic: runtime error: comparing uncomparable type []int
	// fmt.Println(e == f)
	fmt.Println(e)
	fmt.Println(f)

	/*
		tips: []int 是不可比较的类型。下表中列举出了类型及比较的几种情况。
			1. map	宕机错误，不可比较
			2. 切片（[]T）	宕机错误，不可比较
			3. 通道（channel）	可比较，必须由同一个 make 生成，也就是同一个通道才会是 true，否则为 false
			4. 数组（[容量]T）	可比较，编译期知道两个数组是否一致
			5. 结构体	可比较，可以逐个比较结构体的值
			6. 函数	可比较

	*/
}
